package NG::Sys::Loop::Daemon;
use strict;
use warnings;
use utf8;
use POSIX;

use base 'NG::Sys::Loop::Cron';
our $running;
our $restart;
my $count = 0;

sub on_before_loop {
	my ($self) = @_;
	binmode STDOUT,":utf8";
	binmode STDIN,":utf8";
	binmode STDERR,":utf8";

	if(my $pid = $self->can_run){
		die "Another process runing($pid)\n";
	}
	unless($self->{nofork} || $self->arg->{nofork}){
		my $child = fork();
		unless(defined $child){
			die "Cannot fork: '$!'\n";
		}elsif($child){
			return 0;
		}
	$self->warn_to_logger;
	$self->ext_die;
	#$self->die_to_logger;
		unless(POSIX::setsid()){
			die "Cannot POSIX::setsid(): '$!'\n";
		}
	}
	$self->logger->info("started");
	$SIG{INT} = $SIG{TERM} = \&stop;
	$SIG{HUP} = \&restart;
	$self->write_pid;
	$running = 1;
	return 1;
}
sub stop {
	$running = 0;
}
sub restart {
	$running = 0;
	$restart = 1;
}
sub on_init_process {
	my ($self) = @_;
	$self->drop_context;
	return;
}
sub on_done_process {
	my ($self) = @_;
	$self->drop_context;
}
sub on_leave_loop {
	my ($self) = @_;
	unless($running){
		return 1;
	}
	$count++;
	if($self->{restart_after} && $self->{restart_after} <= $count){
		$restart = 1;
		return 1;
	}
	if($self->arg->{count} && $self->arg->{count} <= $count){
		return 1;
	}
	return 0;
}
sub on_delay_loop {
	my ($self) = @_;
	if(my $delay = $self->arg->{delay} || $self->{delay}){
		sleep $delay if $delay > 0;
	}
}
sub on_after_loop {
	my ($self) = @_;
	$self->SUPER::on_after_loop;
	if($restart){
		$self->logger->info("restarted");
		if(-x $self->fullscript){
			exec($self->fullscript);
		}else{
			exec("perl",$self->fullscript);
		}
		die "Cannot exec: '$!'\n";
	}else{
		$self->logger->info("stopped");
	}
}
sub process_error {
	my ($app,$scope,$error) = @_;
	$app->logger->error("LOOP_ERROR[$scope]: ".$error);
}

#####################
#sub on_prepare_loop {
#	my($app) = @_;
#}
#sub on_enter_loop {
#	my($app) = @_;
#	return  1; # yes, enter to loop
#}
#sub on_before_process {
#	my($app) = @_;
#	return 1; # yes, do main process
#}
#sub on_process {
#	my($app) = @_;
#	return 1; # yes, do after_process
#}
#sub on_after_process {
#	my($app) = @_;
#}
##################

1;
